package com.iris.smartclass.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.UUID;
import cn.hutool.core.lang.Validator;
import cn.hutool.core.util.RandomUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.aliyuncs.CommonRequest;
import com.aliyuncs.CommonResponse;
import com.aliyuncs.DefaultAcsClient;
import com.aliyuncs.IAcsClient;
import com.aliyuncs.exceptions.ClientException;
import com.aliyuncs.exceptions.ServerException;
import com.aliyuncs.http.MethodType;
import com.aliyuncs.profile.DefaultProfile;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.iris.smartclass.common.ErrorCode;
import com.iris.smartclass.constant.CommonConstant;
import com.iris.smartclass.exception.BusinessException;
import com.iris.smartclass.mapper.StudentMapper;
import com.iris.smartclass.model.dto.student.StudentLoginRequest;
import com.iris.smartclass.model.dto.student.StudentSendCodeRequest;
import com.iris.smartclass.model.dto.student.StudentQueryRequest;
import com.iris.smartclass.model.entity.Student;
import com.iris.smartclass.model.entity.User;
import com.iris.smartclass.model.vo.ClassDataVO;
import com.iris.smartclass.model.vo.StudentVO;
import com.iris.smartclass.service.StudentService;
import com.iris.smartclass.service.UserService;
import com.iris.smartclass.utils.SqlUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * @author 孙鸣
 * @description 针对表【student(学生)】的数据库操作Service实现
 * @createDate 2024-12-31 09:20:36
 */
@Service
public class StudentServiceImpl extends ServiceImpl<StudentMapper, Student>
        implements StudentService {

    @Resource
    private StudentMapper studentMapper;

    @Resource
    private UserService userService;

    @Resource
    private RedisTemplate<String, String> redisTemplate;

    @Override
    public StudentVO getStudentVO(Student student) {
        if (student == null) {
            return null;
        }
        StudentVO studentVO = new StudentVO();
        BeanUtils.copyProperties(student, studentVO);
        return studentVO;
    }

    @Override
    public List<StudentVO> getStudentVO(List<Student> studentList) {
        if (CollUtil.isEmpty(studentList)) {
            return new ArrayList<>();
        }
        return studentList.stream().map(this::getStudentVO).collect(Collectors.toList());
    }

    @Override
    public ClassDataVO getClassData(HttpServletRequest request) {
        ClassDataVO dataVO = new ClassDataVO();
        User loginUser = userService.getLoginUser(request);
        Long uuid = loginUser.getId();

        dataVO.setTotalPeople(getStudentCountByStatus(uuid, null));
        dataVO.setPresentPeople(getStudentCountByStatus(uuid, 0));
        dataVO.setAbsentPeople(getStudentCountByStatus(uuid, 1));
        dataVO.setLatePeople(getStudentCountByStatus(uuid, 2));

        return dataVO;
    }

    private Long getStudentCountByStatus(Long uuid, Integer absentStatus) {
        QueryWrapper<Student> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("uuid", uuid);
        if (absentStatus != null) {
            queryWrapper.eq("absentStatus", absentStatus);
        }
        return studentMapper.selectCount(queryWrapper);
    }

    @Override
    public boolean sendPhoneCode(StudentSendCodeRequest studentSendCodeRequest) {
        // 校验手机号是否合法
        if (studentSendCodeRequest == null || !Validator.isMobile(studentSendCodeRequest.getPhone())) {
            throw new BusinessException(ErrorCode.PHONE_ERROR);
        }
        // 查询手机号是否存在
        QueryWrapper<Student> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("phone", studentSendCodeRequest.getPhone());
        Student student = studentMapper.selectOne(queryWrapper);
        if (student == null) {
            throw new BusinessException(ErrorCode.PHONE_NOT_FOUND);
        }

        String code = redisTemplate.opsForValue().get("login:code:" + studentSendCodeRequest.getPhone());
        if (StringUtils.isEmpty(code)) {
            // 生成随机验证码
            String randomCode = RandomUtil.randomNumbers(6);
            // 如果没有验证码说明过期，然后存储验证码到redis,并且设置过期时间为2分钟
            redisTemplate.opsForValue().set("login:code:" + studentSendCodeRequest.getPhone(), randomCode, 2, TimeUnit.MINUTES);
            return send(studentSendCodeRequest.getPhone(), randomCode);
        }
        return false;
    }

    @Override
    public boolean send(String phone, String code) {
        // 连接阿里云
        // *********注意：AccessKey ID 和 AccessKey Secret 需要改成你自己的**********
        DefaultProfile profile = DefaultProfile.getProfile("cn-qingdao", "LTAI5t8ujfWKfCu5zorZNK75", "WEAIE0fruCDrNJmabP8uUavypY15Ex");
        IAcsClient client = new DefaultAcsClient(profile);

        // 构建请求
        CommonRequest request = new CommonRequest();

        // 请求方式
        request.setSysMethod(MethodType.POST);

        // 官方需要的和短信请求相关的信息
        request.setSysDomain("dysmsapi.aliyuncs.com");
        request.setSysVersion("2017-05-25");
        request.setSysAction("SendSms");

        // 生成装有短信验证码的map
        Map<String, Object> messageMap = new HashMap<>();
        messageMap.put("code", code);

        // 填写请求参数
        request.putQueryParameter("PhoneNumbers", phone); // 电话
        // *********注意：签名名称 需要改成你自己的**********
        request.putQueryParameter("SignName", "孙鸣的个人学习网站"); // 签名名称
        // *********注意：模板CODE 需要改成你自己的**********
        request.putQueryParameter("TemplateCode", "SMS_309755188"); // 模版CODE
        request.putQueryParameter("TemplateParam", JSONObject.toJSONString(messageMap)); // 短信模板变量对应的实际值

        try {
            // 发送请求并接受返回值
            CommonResponse response = client.getCommonResponse(request);
            // 把json格式字符串变成Json对象
            JSONObject jsonObject = JSON.parseObject(response.getData());
            // 请求状态码，返回OK代表请求成功，来自官方文档
            String resCode = jsonObject.getString("Code");

            return "OK".equals(resCode);
        } catch (ServerException e) {
            e.printStackTrace();
        } catch (ClientException e) {
            e.printStackTrace();
        }

        return false;
    }

    @Override
    public String StudentLoginByPhone(StudentLoginRequest studentLoginRequest) {
        if (studentLoginRequest == null || !Validator.isMobile(studentLoginRequest.getPhone())) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        String code = redisTemplate.opsForValue().get("login:code:" + studentLoginRequest.getPhone());
        if (StringUtils.isEmpty(code)) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "验证码已过期");
        }
        if (!studentLoginRequest.getCode().equals(code)) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "验证码错误");
        }
        Student student = studentMapper.selectOne(new QueryWrapper<Student>().eq("phone", studentLoginRequest.getPhone()));

        StudentVO studentVO = BeanUtil.copyProperties(student,StudentVO.class);
        // 验证码正确
        UUID token = UUID.randomUUID(true);

        redisTemplate.opsForHash().putAll("login:user:"+token, BeanUtil.beanToMap(studentVO));

        //设置过期时间
        redisTemplate.expire("login:user:"+token, 30, TimeUnit.MINUTES);
        return token.toString();
    }


    @Override
    public QueryWrapper<Student> getQueryWrapper(StudentQueryRequest studentQueryRequest, HttpServletRequest request) {
        if (studentQueryRequest == null) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "请求参数为空");
        }
        String name = studentQueryRequest.getName();
        User loginUser = userService.getLoginUser(request);
        Long uuid = loginUser.getId();
        Integer absentStatus = studentQueryRequest.getAbsentStatus();
        String phone = studentQueryRequest.getPhone();
        Integer gender = studentQueryRequest.getGender();
        String role = studentQueryRequest.getRole();
        Integer optionScore = studentQueryRequest.getOptionScore();
        String sortField = studentQueryRequest.getSortField();
        String sortOrder = studentQueryRequest.getSortOrder();
        QueryWrapper<Student> queryWrapper = new QueryWrapper<>();
        queryWrapper.like(StringUtils.isNotBlank(name), "name", name);
        queryWrapper.eq(absentStatus != null, "absentStatus", absentStatus);
        queryWrapper.eq("uuid", uuid);
        queryWrapper.like(StringUtils.isNotBlank(phone), "phone", phone);
        queryWrapper.eq(gender != null, "gender", gender);
        queryWrapper.eq(optionScore != null, "optionScore", optionScore);
        queryWrapper.eq(StringUtils.isNotBlank(role), "role", role);
        queryWrapper.orderBy(SqlUtils.validSortField(sortField), sortOrder.equals(CommonConstant.SORT_ORDER_ASC),
                sortField);
        return queryWrapper;
    }
}




